/**
  Implementacja statycznego słownika
  część projektu na wyszukiwanie informacji
*/

#include<stdio.h>
#include<stdlib.h>
#undef assert
#define assert(X) {if(!(X)){printf("assertion failed on line %d\n >>%s\n", __LINE__, #X);++*((int*)(NULL));}}

struct Node {
  int child;
  char *character;
  int val;
  char count;
};

typedef struct Node Node;

Node *nodes;
char *chars;
int nodeMax;
int nodeCount;
int charMax;
int charCount;


void loadNode ( FILE *file, int num ) {
  Node *this = nodes + num;
//  int dummy;
//  fscanf ( file, "%d%d", &this->val, &dummy );
//    this->count = dummy;
  fread ( &this->val, sizeof(int), 1, file );
  fread ( &this->count, sizeof(char), 1, file );
  
  this->child = nodeCount;
  this->character = chars + charCount;
  nodeCount += this->count; //<malloc
  charCount += this->count;
  int i;
  for ( i = 0; i < this->count; ++i ){
    loadNode ( file, this->child + i );
  }
}

#define This nodes[node]
int get ( int node, char *word ) {
  if ( * ( word ) == 0 )
    return This.val;
  int i = 0;
  
  int lower = 0;
  int upper = This.count - 1;
  while ( upper - lower > 1 ){
    i = lower + (upper-lower)/2;
    if ( This.character[i] < *word ) lower = i+1;
    else upper = i;
  }
  if ( This.character[lower] == *word ) i = lower;
  else if ( This.character[upper] == *word ) i = upper;
  else {
//    assert ( 0 );
    return -1;
  }
  
  /*
  for ( i = 0; i < This.count; ++i ) {
    if ( This.character[i] == *word ) break;
  }
  assert ( i < This.count );
  */
  return get ( This.child + i, word+1 );
}


/**
 *
 *  Interfejs zaczyna się tu
 *
*/

int base = -1;

/// Zwraca wartość, jeżeli nie zdefiniowana zwraca -1
int getVal ( char *word ) {
  return get ( base, word );
}

/// Ładuje słownik z pliku
/// wg formatu z node.c
void load ( char *filename ){
  base = 0;
  nodeCount = 1; //< malloc (1)
  FILE *file = fopen ( filename, "r" );
  if( !file)
  {
    printf("No such file %s\n", filename);
  }
  int n, m;
//  fscanf ( file, "%d%d", &n, &m);
  fread ( &n, sizeof(int), 1, file );
  fread ( &m, sizeof(int), 1, file );
  
  nodes = malloc ( n * sizeof ( Node ) );
  chars = malloc ( m * sizeof ( char ) );
  loadNode ( file, base );
//  fscanf (file, " \n" );
  fread ( chars, 1, m, file );
}

char buf[256];
void dumpDict ( int node, int depth ){
  if ( This.val >= 0  ){
    buf[depth] = 0;
    printf ("%s %d\n", buf, This.val );
  }
  if ( This.count <= 0 ) assert ( This.val >= 0 );
  int i;
  for ( i = 0; i < This.count; ++i ){
    buf[depth] = This.character[i];
    dumpDict ( This.child + i, depth + 1 );
  }
}

/*
int main (){
  load ( "static_node.dat" );
  dumpDict ( base, 0 );
}
*/
